<?php
/**
 * Douphp生成缩略图、水印
 */
define('IN_DOUCO', true);
define('EXIT_INIT',true);
require (dirname(__FILE__) . '/include/init.php');
/**
 * 图像处理接口
 *
 * @package     wf.image
 * @author      cm <cmpan@qq.com>
 * @link        http://docs.windwork.org/manual/wf.image.html
 * @since       0.1.0
 */
interface ImageInterface
{


    public function setImage($imageContent);

    public function thumb($thumbWidth, $thumbHeight, $isCut = true, $cutPlace = 5, $quality = 95, $thumbType = 'jpg');

    public function watermark($watermarkFile = 'static/images/watermark.png', $watermarkPlace = 9, $quality = 95);

}


class GD implements ImageInterface
{
    /**
     * 图片相关信息
     *
     * @var array
     */
    protected $imgInfo = '';

    /**
     * 图片二进制内容
     * @var string
     */
    protected $imageContent = '';

    /**
     * 缩略图背景颜色
     * @var array
     */
    protected $bgColor = [255, 255, 255];
    /**
     * @var string
     */
    protected $thumbType = 'jpg';


    public function __construct()
    {
        if (!function_exists('gd_info')) {
            throw new Exception('你的php没有使用gd2扩展，不能处理图片');
        }
        @ini_set("memory_limit", "512M");  // 处理大图片的时候要较较大的内存
    }


    public function setImage($imageContent)
    {
        if (!$imageContent || false == ($this->imgInfo = @getimagesizefromstring($imageContent))) {
            throw new Exception('错误的图片文件！');;
        }

        $this->imageContent = $imageContent;

        return $this;
    }

    public function setBgColor($r, $g, $b)
    {
        $this->bgColor = [$r, $g, $b];
    }

    public function thumb($thumbWidth, $thumbHeight, $isCut = true, $cutPlace = 5, $quality = 95, $thumbType = 'jpg')
    {
        if (!in_array($thumbType, ['jpg', 'png', 'webp'])) {
            throw new Exception('thumb image type must be webp|jpg|png');
        }

        if($isCut) {
            return $this->thumbCutOut($thumbWidth, $thumbHeight, $cutPlace, $quality, $thumbType);
        } else {
            return $this->thumbUnCut($thumbWidth, $thumbHeight, $quality, $thumbType);
        }
    }

    private function thumbUnCut($thumbWidth, $thumbHeight, $quality, $thumbType = 'jpg')
    {
        list($srcW, $srcH) = $this->imgInfo;

        // 宽或高按比例缩放
        if ($thumbWidth == 0 || $thumbHeight == 0) {
            if ($thumbWidth == 0) {
                $thumbHeight = $srcH * ($thumbWidth / $srcW);
            } else {
                $thumbWidth = $thumbWidth = $srcW * ($thumbHeight/$srcH);
            }
            $imgW = $thumbWidth; // 图片显示宽
            $imgH = $thumbHeight; // 图片显示高
            $posX = 0;
            $posY = 0;
        } else {
            if ($thumbWidth/$thumbHeight < $srcW/$srcH) {
                // 宽比例超过，补上高
                $imgW = $thumbWidth; // 图片显示宽
                $imgH = $thumbWidth * $srcH / $srcW; // 图片显示高
                $posX = 0;
                $posY = ($thumbHeight - $imgH) / 2;
            } else {
                // 高比例超过，补上宽
                $imgH = $thumbHeight; // 图片显示宽
                $imgW = $thumbHeight * $srcW / $srcH; // 图片显示高
                $posX = ($thumbWidth - $imgW) / 2;
                $posY = 0;
            }
        }

        $thumbImage = imagecreatetruecolor($thumbWidth, $thumbHeight);

        // 填充背景色
        $fillColor = imagecolorallocate($thumbImage, $this->bgColor[0], $this->bgColor[1], $this->bgColor[2]);
        imagefill($thumbImage, 0, 0, $fillColor);
        // 合上图
        $attachImage = imagecreatefromstring($this->imageContent);
        imagecopyresized($thumbImage, $attachImage, $posX, $posY, 0, 0, $imgW, $imgH, $srcW, $srcH);

        // 为兼容云存贮设备，不直接把缩略图写入文件系统，而是返回文件内容
        ob_start();
        if ($thumbType == 'webp') {
            imagewebp($thumbImage, null, $quality);
        } elseif ($thumbType == 'png') {
            imagepng($thumbImage, null, floor($quality/10));
        } else {
            imagejpeg($thumbImage, null, $quality);
        }
        $thumb = ob_get_clean();
        imagedestroy($attachImage);
        imagedestroy($thumbImage);

        if(!$thumb) {
            throw new Exception('无法生成缩略图');
        }

        return $thumb;
    }

    private function thumbCutOut($thumbWidth, $thumbHeight, $cutPlace = 5, $quality = 100, $thumbType = 'jpg')
    {
        list($srcW, $srcH) = $this->imgInfo;

        $imgH = $srcH;  // 取样图片高
        $imgW = $srcW;  // 取样图片宽
        $srcX = 0; // 取样图片x坐标开始值
        $srcY = 0; // 取样图片y坐标开始值

        $attachImage = imagecreatefromstring($this->imageContent);

        if($thumbWidth == 0){
            // 宽等比例缩放
            $thumbWidth = $srcW * ($thumbHeight / $srcH);
        } elseif ($thumbHeight == 0) {
            // 高等比例缩放
            $thumbHeight = $srcH * ($thumbWidth / $srcW);
        } else {
            // 需要裁剪
            if((($thumbWidth / $imgW) * $imgH) > $thumbHeight) {
                // 高需要截掉
                $imgH = ($imgW / $thumbWidth) * $thumbHeight;

                // 高开始截取位置
                if (in_array($cutPlace, [4, 5, 6])) {
                    $srcY = ($srcH - $imgH)/2;
                } elseif (in_array($cutPlace, [7, 8, 9])) {
                    $srcY = $srcH - $imgH;
                }
            } else {
                // 宽需要截掉
                $imgW = ($imgH / $thumbHeight) * $thumbWidth;

                if (in_array($cutPlace, [2, 5, 8])) {
                    $srcX = ($srcW - $imgW)/2;
                } elseif (in_array($cutPlace, [3, 6, 9])) {
                    $srcX = $srcW - $imgW;
                }
            }
        }

        // 如果不设置缩略图保存路径则保存到原始文件所在目录
        $thumbImage = imagecreatetruecolor($thumbWidth, $thumbHeight);
        if($this->imgInfo['mime'] == 'image/gif') {
            imagecolortransparent($attachImage, imagecolorallocate($attachImage, $this->bgColor[0], $this->bgColor[1], $this->bgColor[2]));
        } else if($this->imgInfo['mime'] == 'image/png') {
            imagealphablending($thumbImage , false);//关闭混合模式，以便透明颜色能覆盖原画布
            imagesavealpha($thumbImage, true);
        }

        // 重采样拷贝部分图像并调整大小到$thumbImage
        imagecopyresampled($thumbImage, $attachImage ,0, 0, $srcX, $srcY, $thumbWidth, $thumbHeight, $imgW, $imgH);
        // 为兼容云存贮设备，这里不直接把缩略图写入文件系统
        ob_start();
        if ($thumbType == 'webp') {
            imagewebp($thumbImage, null, $quality);
        } elseif ($thumbType == 'png') {
            imagepng($thumbImage, null, floor($quality/10));
        } else {
            imagejpeg($thumbImage, null, $quality);
        }
        $thumb = ob_get_clean();
        imagedestroy($attachImage);
        imagedestroy($thumbImage);

        if(!$thumb) {
            throw new Exception('无法生成缩略图');
        }

        return $thumb;
    }

    public function watermark($watermarkFile = 'images/watermark.png', $watermarkPlace = 9, $quality = 95)
    {
        @list($imgW, $imgH) = $this->imgInfo;

        $watermarkInfo    = @getimagesize($watermarkFile);
        $watermarkLogo    = ('image/png' == $watermarkInfo['mime']) ? @imagecreatefrompng($watermarkFile) : @imagecreatefromgif($watermarkFile);
        if(!$watermarkLogo) {
            return;
        }
        list($logoW, $logoH) = $watermarkInfo;
        $wmwidth = $imgW - $logoW;
        $wmheight = $imgH - $logoH;
        if(is_readable($watermarkFile) && $wmwidth > 10 && $wmheight > 10) {
            switch($watermarkPlace) {
                case 1:
                    $x = +5;
                    $y = +5;
                    break;
                case 2:
                    $x = ($imgW - $logoW) / 2;
                    $y = +5;
                    break;
                case 3:
                    $x = $imgW - $logoW - 5;
                    $y = +5;
                    break;
                case 4:
                    $x = +5;
                    $y = ($imgH - $logoH) / 2;
                    break;
                case 5:
                    $x = ($imgW - $logoW) / 2;
                    $y = ($imgH - $logoH) / 2;
                    break;
                case 6:
                    $x = $imgW - $logoW;
                    $y = ($imgH - $logoH) / 2;
                    break;
                case 7:
                    $x = +5;
                    $y = $imgH - $logoH - 5;
                    break;
                case 8:
                    $x = ($imgW - $logoW) / 2;
                    $y = $imgH - $logoH - 5;
                    break;
                case 9:
                    $x = $imgW - $logoW - 5;
                    $y = $imgH - $logoH - 5;
                    break;
            }
            $dstImage = imagecreatetruecolor($imgW, $imgH);
            imagefill($dstImage, 0, 0, imagecolorallocate($dstImage, $this->bgColor[0], $this->bgColor[1], $this->bgColor[2]));
            $targetImage = @imagecreatefromstring($this->imageContent);

            imageCopy($dstImage, $targetImage, 0, 0, 0, 0, $imgW, $imgH);
            imageCopy($dstImage, $watermarkLogo, $x, $y, 0, 0, $logoW, $logoH);
            ob_start();
            imagejpeg($dstImage, null, $quality);
            $ret = ob_get_clean();
            return $ret;
        }
    }
    /**
     * 获取GD库版本
     */
    public function getExtVersion()
    {
        if(!function_exists('gd_info')) {
            return false;
        }

        $gdInfo = gd_info();
        return 'GD ' . $gdInfo['GD Version'];
    }

}


/**
 * 业务逻辑
 */


//解密文件名，根据hashcode

$file = thumb_encrypt($_REQUEST['src'],'D');
$file = str_replace(ROOT_URL,'',$file);
//本地图片
if(!$_REQUEST['remote'])
{
    $file = ROOT_PATH .$file;
}

if(!is_image($file)){
    exit('图片文件无效！');
}
//缩略图
$thumb_width = $_REQUEST['w']?$_REQUEST['w']:400;
$thumb_height = $_REQUEST['h']?$_REQUEST['h']:400;
$is_cut = $_REQUEST['cut']?true:false;                           //是否裁剪图片，true）裁掉超过比例的部分；false）不裁剪图片，图片缩放显示，增加白色背景
$cut_place = $_REQUEST['cut_place']?$_REQUEST['cutPlace']:5;         //裁剪保留位置 1:左上, 2：中上， 3右上, 4：左中， 5：中中， 6：右中，7：左下， 8：中下，9右下
$img = new GD();
$img->setImage(file_get_contents($file));
$content = $img->thumb($thumb_width, $thumb_height,$is_cut,$cut_place);

//水印
$is_water = $_REQUEST['water']?true:false;
$water_pos = $_REQUEST['water_pos']?$_REQUEST['water_pos']:9;   //水印放置位置 1:左上, 2：中上， 3右上, 4：左中， 5：中中， 6：右中，7：左下， 8：中下，9右下
if($is_water){
    $img->setImage($content);
    $content = $img->watermark(ROOT_PATH.'data/watermark.png',$water_pos);
}

header("Content-Type:image/jpeg");
echo $content;



/**
 * 获取文件后缀
 * @param type $file
 * @return type
 */
function get_fileext($file = '')
{
    return strtolower(substr(strrchr($file, '.'), 1));
}

/**
 * 判断文件是不是一个图片
 * @param type $img
 * @return type
 */
function is_image($img = '')
{
    return in_array(strtolower(get_fileext($img)), array('gif', 'jpg', 'jpeg', 'png', 'bmp'));
}


/**
 * 加解密函数
 * @param $string
 * @param $operation
 * @param string $key
 * @return bool|mixed|string
 */
function thumb_encrypt($string,$operation,$key=DOU_ID){
    $key=md5($key);
    $key_length=strlen($key);
    $string=$operation=='D'?base64_decode($string):substr(md5($string.$key),0,8).$string;
    $string_length=strlen($string);
    $rndkey=$box=array();
    $result='';
    for($i=0;$i<=255;$i++){
        $rndkey[$i]=ord($key[$i%$key_length]);
        $box[$i]=$i;
    }
    for($j=$i=0;$i<256;$i++){
        $j=($j+$box[$i]+$rndkey[$i])%256;
        $tmp=$box[$i];
        $box[$i]=$box[$j];
        $box[$j]=$tmp;
    }
    for($a=$j=$i=0;$i<$string_length;$i++){
        $a=($a+1)%256;
        $j=($j+$box[$a])%256;
        $tmp=$box[$a];
        $box[$a]=$box[$j];
        $box[$j]=$tmp;
        $result.=chr(ord($string[$i])^($box[($box[$a]+$box[$j])%256]));
    }
    if($operation=='D'){
        if(substr($result,0,8)==substr(md5(substr($result,8).$key),0,8)){
            return substr($result,8);
        }else{
            return'';
        }
    }else{
        return str_replace('=','',base64_encode($result));
    }
}